package com.yuan.Service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuan.Mapper.OrderDetailMapper;
import com.yuan.Mapper.OrderMapper;
import com.yuan.Mapper.ShoppingCartMapper;
import com.yuan.Service.AddressBookService;
import com.yuan.Service.OrderService;
import com.yuan.constant.MessageConstant;
import com.yuan.context.BaseContext;
import com.yuan.dto.*;
import com.yuan.entity.AddressBook;
import com.yuan.entity.OrderDetail;
import com.yuan.entity.Orders;
import com.yuan.entity.ShoppingCart;
import com.yuan.exception.AddressBookBusinessException;
import com.yuan.exception.OrderBusinessException;
import com.yuan.exception.ShoppingCartBusinessException;
import com.yuan.result.PageResult;
import com.yuan.vo.OrderStatisticsVO;
import com.yuan.vo.OrderSubmitVO;
import com.yuan.vo.OrderVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {

    @Autowired
    private AddressBookService addressBookService;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;

    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {

        LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<>();
        Page<Orders> page = new Page<>(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());

        LocalDateTime beginTime = ordersPageQueryDTO.getBeginTime();
        LocalDateTime endTime = ordersPageQueryDTO.getEndTime();
        String number = ordersPageQueryDTO.getNumber();
        String phone = ordersPageQueryDTO.getPhone();
        Integer status = ordersPageQueryDTO.getStatus();
        Long userId = ordersPageQueryDTO.getUserId();

        if (beginTime != null) {
            wrapper.ge(Orders::getOrderTime, beginTime);
        }
        if (endTime != null) {
            wrapper.le(Orders::getOrderTime, endTime);
        }
        if (number != null) {
            wrapper.eq(Orders::getNumber, number);
        }
        if (phone != null) {
            wrapper.eq(Orders::getPhone, phone);
        }
        if (status != null) {
            wrapper.eq(Orders::getStatus, status);
        }
        if (userId != null) {
            wrapper.eq(Orders::getUserId, userId);
        }
        Page<Orders> paged = page(page, wrapper);
        List<Orders> records = paged.getRecords();
//        OrderVO orderVO = new OrderVO();
        List<OrderVO> orderVOList = new ArrayList<>();
        for (Orders Order : records) {
            OrderVO orderVO = new OrderVO();
            LambdaQueryWrapper<OrderDetail> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(OrderDetail::getOrderId, Order.getId());
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(wrapper1);
            List<String> list = orderDetails.stream().map(s -> {
                String orderDish = s.getName() + "*" + s.getNumber() + ",";
                return orderDish;
            }).toList();
            String join = String.join("", list);
            orderVO.setOrderDishes(join);
            orderVO.setOrderDetailList(orderDetails);
            orderVOList.add(orderVO);
        }

        return new PageResult(paged.getTotal(), orderVOList);
    }

    @Override
    public OrderStatisticsVO statistics() {


        //2待接单
        Long count1 = baseMapper.selectCount(new LambdaQueryWrapper<Orders>().eq(Orders::getStatus, 2));

        //待派送
        Long count2 = baseMapper.selectCount(new LambdaQueryWrapper<Orders>().eq(Orders::getStatus, 3));
        //派送中
        Long count3 = baseMapper.selectCount(new LambdaQueryWrapper<Orders>().eq(Orders::getStatus, 4));

        OrderStatisticsVO vo = new OrderStatisticsVO();
        vo.setToBeConfirmed(Integer.valueOf(count1.toString()));
        vo.setConfirmed(Integer.valueOf(count2.toString()));
        vo.setDeliveryInProgress(Integer.valueOf(count3.toString()));
        return null;
    }

    @Override
    public OrderVO details(Long id) {


        List<OrderDetail> orderDetails = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, id));
        OrderVO orderVO = new OrderVO();
        orderVO.setOrderDetailList(orderDetails);
        StringBuilder sb = new StringBuilder();
        for (OrderDetail detail : orderDetails) {
            String s = detail.getName() + "*" + detail.getNumber();
            sb.append(s);
        }
        orderVO.setOrderDishes(sb.toString());
        orderVO.setOrderDetailList(orderDetails);
        return orderVO;
    }

    @Override
    public void confirm(OrdersConfirmDTO ordersConfirmDTO) {
        Orders orders = Orders.builder().id(ordersConfirmDTO.getId()).status(ordersConfirmDTO.getStatus()).build();

        updateById(orders);
    }

    @Override
    public void rejection(OrdersRejectionDTO ordersRejectionDTO) {

        Orders ordersDB = getById(ordersRejectionDTO.getId());
        //订单只有存在且状态为2（待接单）才可以拒单
        if (ordersDB == null || !ordersDB.getStatus().equals(Orders.TO_BE_CONFIRMED)) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        //支付状态
        Integer payStatus = ordersDB.getPayStatus();
        if (payStatus == Orders.PAID) {
            //用户已支付，需要退款
//            String refund = weChatPayUtil.refund(
//                    ordersDB.getNumber(),
//                    ordersDB.getNumber(),
//                    new BigDecimal(0.01),
//                    new BigDecimal(0.01));
//            log.info("申请退款：{}", refund);
        }
        // 拒单需要退款，根据订单id更新订单状态、拒单原因、取消时间
        Orders orders = new Orders();
        orders.setId(ordersDB.getId());
        orders.setStatus(Orders.CANCELLED);
        orders.setRejectionReason(ordersRejectionDTO.getRejectionReason());
        orders.setCancelTime(LocalDateTime.now());

        updateById(orders);

    }

    @Override
    public void cancel(OrdersCancelDTO ordersCancelDTO) {
        // 根据id查询订单
        Orders ordersDB = getById(ordersCancelDTO.getId());

        //支付状态
        Integer payStatus = ordersDB.getPayStatus();
        if (payStatus == 1) {
         /*   //用户已支付，需要退款
            String refund = weChatPayUtil.refund(
                    ordersDB.getNumber(),
                    ordersDB.getNumber(),
                    new BigDecimal(0.01),
                    new BigDecimal(0.01));
            log.info("申请退款：{}", refund);*/
        }

        // 管理端取消订单需要退款，根据订单id更新订单状态、取消原因、取消时间
        Orders orders = new Orders();
        orders.setId(ordersCancelDTO.getId());
        orders.setStatus(Orders.CANCELLED);
        orders.setCancelReason(ordersCancelDTO.getCancelReason());
        orders.setCancelTime(LocalDateTime.now());
        updateById(orders);
    }

    @Override
    public void delivery(Long id) {
        Orders ordersDB = getById(id);
        // 校验订单是否存在，并且状态为3
        if (ordersDB == null || !ordersDB.getStatus().equals(Orders.CONFIRMED)) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }


        Orders orders = new Orders();
        orders.setId(ordersDB.getId());

        orders.setStatus(Orders.DELIVERY_IN_PROGRESS);

        updateById(orders);

    }

    @Override
    public void complete(Long id) {
        // 根据id查询订单
        Orders ordersDB = getById(id);
        // 校验订单是否存在，并且状态为4
        if (ordersDB == null || !ordersDB.getStatus().equals(Orders.DELIVERY_IN_PROGRESS)) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        Orders orders = new Orders();
        orders.setId(ordersDB.getId());
        // 更新订单状态,状态转为完成
        orders.setStatus(Orders.COMPLETED);
        orders.setDeliveryTime(LocalDateTime.now());

        updateById(orders);

    }

    @Override
    public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {

        AddressBook addressBook = addressBookService.getById(ordersSubmitDTO.getAddressBookId());
        if (addressBook == null) {
            //抛出业务异常
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        //检查用户的收货地址是否超出配送范围
        //checkOutOfRange(addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail());
        //查询当前用户的购物车数据
        Long userId = BaseContext.getCurrentId();

        ShoppingCart shoppingCart = new ShoppingCart();
//        shoppingCart.setUserId(userId);
        List<ShoppingCart> shoppingCartList = shoppingCartMapper.selectList(new LambdaQueryWrapper<ShoppingCart>().eq(ShoppingCart::getUserId, userId)
        );
        if (shoppingCartList == null || shoppingCartList.size() == 0) {
            //抛出业务异常
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }
        //2. 向订单表插入1条数据
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        orders.setAddress(addressBook.getDetail());
        orders.setPhone(addressBook.getPhone());
        orders.setConsignee(addressBook.getConsignee());
        orders.setUserId(userId);

        save(orders);
        List<OrderDetail> orderDetailList = new ArrayList<>();
        //3. 向订单明细表插入n条数据
        for (ShoppingCart cart : shoppingCartList) {
            OrderDetail orderDetail = new OrderDetail();//订单明细
            BeanUtils.copyProperties(cart, orderDetail);
            orderDetail.setOrderId(orders.getId());//设置当前订单明细关联的订单id
            orderDetailList.add(orderDetail);
        }
        orderDetailMapper.insert(orderDetailList);

        shoppingCartMapper.delete(new LambdaQueryWrapper<ShoppingCart>().eq(ShoppingCart::getUserId, userId));

        OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
                .id(orders.getId())
                .orderTime(orders.getOrderTime())
                .orderNumber(orders.getNumber())
                .orderAmount(orders.getAmount())
                .build();

        return orderSubmitVO;
    }


}
